package com.longway.core.toolbox.wdp.api;

import java.util.Map;
import java.util.concurrent.Callable;

import com.jfinal.kit.JsonKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.longway.core.toolbox.cache.ICache;
import com.longway.core.toolbox.utils.HttpUtils;
import com.longway.core.toolbox.utils.RetryUtils;
import com.longway.core.toolbox.wdp.WdpConfig;
import com.longway.core.toolbox.wdp.WdpConfigKit;

public class AuthorizationInfoApi {
    private static String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=";
    private static String refreshUrl = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=";

    private static final String cachePrefix = "authorization:";

    /**
     * 获取 AuthorizationInfo保存到库里
     * @return AuthorizationInfo AuthorizationInfo
     */
    public static AuthorizationInfo getAuthorizationInfo(String authCode) {
    	WdpConfig wdp = WdpConfigKit.getWdpConfig();
    	AuthorizationInfo result = getAuthorizerAccessToken(wdp,authCode);
        return result;
    }
    

    /**
     * 直接获取 AuthorizerAccessToken 字符串，方便使用
     * @return String AuthorizerAccessToken
     */
    public static String getAuthorizerAccessToken(String authCode) {
        return getAuthorizationInfo(authCode).getAuthorizerAccessToken();
    }
    
    public static AuthorizationInfo getAuthorizationInfofromFactory(String appId) {
    	ICache accessTokenCache = ApiConfigKit.getAccessTokenCache();
    	String authinfoJson = accessTokenCache.get(cachePrefix + ":"+ appId);
    	AuthorizationInfo authinfo;
    	if(StrKit.notBlank(authinfoJson)){
    		authinfo = new AuthorizationInfo(authinfoJson);
    	}else{
    		authinfo = WdpConfigKit.getAuthorizationInfoFactory().getAuthorizationInfo(appId);
    		accessTokenCache.set(cachePrefix + ":"+ appId, JsonKit.toJson(authinfo));
    	}
    	if(authinfo.isAvailable()){
    		return authinfo;
    	}else{
    		WdpConfig wdp = WdpConfigKit.getWdpConfig();
    		authinfo = refreshAuthorizerAccessToken(wdp ,authinfo);
    	}
    	return authinfo;
    }
    
    public static String getAuthorizationInfoAccessToken(String appId) {
    	AuthorizationInfo authinfo = getAuthorizationInfofromFactory(appId);
    	return authinfo.getAuthorizerAccessToken();
    }
    
    /**
     * 获取 AuthorizerAccessToken 值
     * @param WdpConfig
     * @return AuthorizationInfo
     */
    private static AuthorizationInfo getAuthorizerAccessToken(WdpConfig wdp,String authCode) {
        String appId = wdp.getAppId();
        final Map<String, String> queryParas = Ret.create("component_appid", appId)
        		.set("authorization_code", authCode);
        String componentAccessToken = ComponentAccessTokenApi.getComponentAccessTokenStr();
        // 最多三次请求
        AuthorizationInfo result = RetryUtils.retryOnException(3, new Callable<AuthorizationInfo>() {
            @Override
            public AuthorizationInfo call() throws Exception {
                String json = HttpUtils.post(url+componentAccessToken, JsonKit.toJson(queryParas)); //HttpUtils.post(url, JsonKit.toJson(queryParas));
                return new AuthorizationInfo(json);
            }
        });
        return result;
    }
    
    //刷新接口调用令牌
    private static  AuthorizationInfo refreshAuthorizerAccessToken(WdpConfig wdp,AuthorizationInfo authInfo) {
        String appId = wdp.getAppId();
        final Map<String, String> queryParas = Ret.create("component_appid", appId)
        		.set("authorizer_appid", authInfo.getAuthorizerAppid())
        		.set("authorizer_refresh_token", authInfo.getAuthorizerRefreshToken());
        String componentAccessToken = ComponentAccessTokenApi.getComponentAccessTokenStr();
        // 最多三次请求
        AuthorizationRefreshInfo result = RetryUtils.retryOnException(3, new Callable<AuthorizationRefreshInfo>() {
            @Override
            public AuthorizationRefreshInfo call() throws Exception {
                String json = HttpUtils.post(refreshUrl+componentAccessToken, JsonKit.toJson(queryParas)); 
                return new AuthorizationRefreshInfo(json);
            }
        });

        if (null != result) {
        	authInfo.setAuthorizerAccessToken(result.getAuthorizerAccessToken());
        	authInfo.setAuthorizerRefreshToken(result.getAuthorizerRefreshToken());
        	authInfo.setExpiredTime(result.getExpiredTime());
        	authInfo.setExpiresIn(result.getExpiresIn());
        }
        return authInfo;
    }
}
